opencv+android环境搭建问题避雷+ Android opencv人脸识别代码

您所在的位置:网站首页 opencv 滚动条 opencv+android环境搭建问题避雷+ Android opencv人脸识别代码

opencv+android环境搭建问题避雷+ Android opencv人脸识别代码

2023-06-06 09:39| 来源: 网络整理| 查看: 265

 以网上大部分用opencvManager来配置的案例,笔者也配置了一下opencv,对一些别人配置过程中没有说清楚或者有问题的一些点进行剖析。

->坑点1:OpenCV error: Cannot load info library for OpenCV

这个据说要加一个libopencv_info的动态库,但是如果只是作基础的图像处理测试,没有这个必要去管这个错误,网上某些下载这个库还要钱,没必要浪费时间在此。

->坑点2:unsatitisfied ldopen fail:libopencv_java3 not found

这个问题网上的处理方式大多写的不全面或者不对。除了DefaultConfig下的ndk配置和版本确实要改以外,以及apply for Kotin……要去掉,版本问题以外(以上配置是确实需要改的,可以参考别人文章),针对这种问题网上给出的解决方式都是在gradle底下加

sourceSet{ jniLib.src{ ……} },或者创建一个JNI folder把库文件丢进去,笔者都试过都不能有效解决问题,打开app底下发现这些库文件根本就没有导入到手机里面去,日志卡死在

System.loadLibrary那句闪退或者报错。

这个问题要通过引入native C++调用CMakeList引入才能成功引入,配置如下:

set(opencv_dir ${CMAKE_SOURCE_DIR}/opencv) add_library(libopencv_java3 SHARED IMPORTED) set_target_properties(libopencv_java3 PROPERTIES IMPORTED_LOCATION ${opencv_dir}/libopencv_java3.so) find_library( # Sets the name of the path variable. log-lib # Specifies the name of the NDK library that # you want CMake to locate. log ) target_link_libraries( # Specifies the target library. native-lib libopencv_java3 # Links the target library to the log library # included in the NDK. ${log-lib} )

如果有不太清楚CMakeList怎么玩的可以看笔者之前的博文:android+jni引入第三方库的文章。

然后loadLibrary就可以成了。需要相关库文件的可以加QQ653166967私我。

测试代码(ImageView自己在xml摆好位置):

if (!OpenCVLoader.initDebug()) { Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization"); OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_4_0, this, mLoaderCallback); }Mat src = new Mat(); Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(), R.drawable.teacher_img); Utils.bitmapToMat(bitmap, src); Imgproc.cvtColor(src, src, Imgproc.COLOR_BGR2GRAY); Mat dst = new Mat(); Imgproc.cvtColor(src, dst, Imgproc.COLOR_GRAY2RGBA); Bitmap bitmap2 = Bitmap.createBitmap(dst.cols(), dst.rows(), Bitmap.Config.ARGB_8888); Utils.matToBitmap(dst,bitmap2); ImageView imageView=findViewById(R.id.welcome_img); imageView.setImageBitmap(bitmap2);

以下人脸识别的代码需要引入的类:(注意这里要求在R.res底下已经包含级联分类器的资源,否则会无法找到资源报错)

package com.example.stuclient; import android.content.Context; import android.os.Build; import android.util.Log; import android.view.SurfaceView; import android.view.View; import androidx.annotation.RequiresApi; import org.opencv.android.CameraBridgeViewBase; import org.opencv.android.JavaCameraView; import org.opencv.core.Mat; import org.opencv.core.MatOfRect; import org.opencv.core.Rect; import org.opencv.core.Scalar; import org.opencv.core.Size; import org.opencv.imgproc.Imgproc; import org.opencv.objdetect.CascadeClassifier; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; public class OpenCVFaceDelect implements CameraBridgeViewBase.CvCameraViewListener2 { //MainActivity的上下文 Context appCtx; //是否检测到 boolean isDelected=false; private Mat mRgba =null; //RGBA private Mat mGray =null; //单通道灰度图 private Mat res; private MatOfRect frontalFaces; private Mat tmpGrayMat=null,tmpRGBMat=null; private CascadeClassifier mFrontalFaceClassifier; private JavaCameraView javaCameraView; final String TAG="opencvFaceDelect"; public static Mat rotate(Mat src, double angele) { Mat dst = src.clone(); org.opencv.core.Point center = new org.opencv.core.Point(src.width() / 2, src.height() / 2); Mat affineTrans = Imgproc.getRotationMatrix2D(center, angele, 1.0); Imgproc.warpAffine(src, dst, affineTrans, dst.size(), Imgproc.INTER_NEAREST); return dst; } @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1) @Override public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) { if(mRgba!=null) { mRgba.release(); mRgba=null; } if(mGray!=null) { mGray.release(); mGray=null; } if(tmpGrayMat!=null) { tmpGrayMat.release(); tmpGrayMat=null; } if(tmpRGBMat!=null) { tmpRGBMat.release(); tmpRGBMat=null; } if(res!=null) { res.release(); res=null; } mRgba = inputFrame.rgba(); //RGBA mGray = inputFrame.gray(); //单通道灰度图 for(int i=0;i 0) { area = mFrontalFacesArray[0].area(); width = mFrontalFacesArray[0].width; } mCurrentFaceSize = mFrontalFacesArray.length; } if (mCurrentFaceSize > 0){ for (int i = 0; i < mFrontalFacesArray.length; i++) { //用框标记 Imgproc.rectangle(tmpRGBMat, mFrontalFacesArray[i].tl(), mFrontalFacesArray[i].br(), new Scalar(0, 255, 0, 255), 3); } mFrontalFacesArray=null; frontalFaces.release(); frontalFaces=null; return tmpRGBMat; } else { frontalFaces.release(); frontalFaces=null; tmpGrayMat.release(); tmpGrayMat=null; tmpRGBMat.release(); tmpRGBMat=null; return null; } } public void initOpencv() { try { //OpenCV的人脸模型文件: haarcascade_frontalface_alt InputStream is = appCtx.getResources().openRawResource(R.raw.haarcascade_frontalface_alt); File cascadeDir = appCtx.getDir("cascade", Context.MODE_PRIVATE); File mCascadeFile = new File(cascadeDir, "haarcascade_frontalface_alt.xml"); FileOutputStream os = new FileOutputStream(mCascadeFile); byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = is.read(buffer)) != -1) { os.write(buffer, 0, bytesRead); } is.close(); os.close(); // 加载 人脸分类器 mFrontalFaceClassifier = new CascadeClassifier(mCascadeFile.getAbsolutePath()); } catch (Exception e) { Log.e(TAG, e.toString()); } javaCameraView.enableView(); } OpenCVFaceDelect(Context context,JavaCameraView view) { appCtx=context; javaCameraView=view; javaCameraView.setCvCameraViewListener(this); } @Override public void onCameraViewStarted(int width, int height) { } @Override public void onCameraViewStopped() { } }

在MainActivity使用时:

JavaCameraView javaCameraView= (JavaCameraView) findViewById(R.id.javaCameraView); openCVFaceDelect=new OpenCVFaceDelect(this,javaCameraView); openCVFaceDelect.initOpencv();

就可以实现人脸检测的功能(手机360度旋转都可以识别)

需要注意的是识别时对应界面默认转到对应方向,还有frame的大小没有设置在其它手机可能超过控件的大小导致JavaCameraView的视图受影响,笔者做这个目的只是检测人脸存在所以没有去顾及这些问题。



【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3